#include "ConversationManager.h"
#include "../InputManager.h"
#include "../GraphicManager.h"

const int kiMessage_X = 1;
const int kiMessage_Y = 20;
const int kiIdentation = 3;

void cConversationManager::Init(string lacConversationFile ) {
	mbIsInConversation = false;
	TiXmlDocument doc(lacConversationFile);
	bool lbLoadOk = doc.LoadFile();

	if (lbLoadOk) {
		OutputDebugString("XML Conversation Load: OK\n");
		TiXmlNode* pParent = &doc;
		stringstream strBuffer;

		// We access to the Level tag
		pParent = pParent->FirstChild()->NextSibling();
	   ReadCharacters(pParent);
		ReadConversations(pParent);
	}
	else {
		OutputDebugString("XML Conversation Load: FAILED\n");
	}
}

void cConversationManager::Update(float lfTimestep) {
	const cInputAction& lActionAccept = cInputManager::Get().GetAction( eIA_Accept);
	const cInputAction& lActionUp = cInputManager::Get().GetAction( eIA_Up);
	const cInputAction& lActionDown = cInputManager::Get().GetAction( eIA_Down);
	if ( mpCurrentConversationNode->meType == eNormalTalk ){
			// Decrease the message time
			mfMessageTime -= lfTimestep;

			
			if ( mfMessageTime <= 0.0f || lActionAccept.GetBecomePressed() ) {
				// Need to continue with the next message or node
				NextMessage(0);
			}
	}
   else if ( mpCurrentConversationNode->meType == eChooseTalk ) {
		if ( lActionAccept.GetBecomePressed()) {
			NextMessage( muiChooseOption );
		}
		if (lActionUp.GetBecomePressed() && muiChooseOption > 0) {
			muiChooseOption--;
		}
		if (lActionDown.GetBecomePressed() && muiChooseOption < mpCurrentConversationNode->mChildren.size() - 1) {
			muiChooseOption++;
		}
   }
	if (mpCurrentConversationNode->mChildren[0].meType == eEndConversation)
		mbIsInConversation = false;
}

void cConversationManager::Render() {
	cGraphicManager & lGraphic = cGraphicManager::Get();
	if ( mpCurrentConversationNode->meType == eNormalTalk ) {
		string lMessage; 
		lMessage.append(SearchNameCharacter(mpCurrentConversationNode->miCharacterId));
		lMessage.append( ": " + mpCurrentConversationNode->macText);
		lGraphic.SetColor(eYellow, eBlack);
		lGraphic.WriteChars(kiMessage_X, kiMessage_Y, lMessage.c_str());
	}
   else if ( mpCurrentConversationNode->meType == eChooseTalk ) {
		int luiSize = mpCurrentConversationNode->mChildren.size();
		for (int luiIndex = 0; luiIndex < luiSize; luiIndex++) {
			string lMessage; 
			if (luiIndex == muiChooseOption)
				lGraphic.SetColor(eBlack, eRed);
			else
				lGraphic.SetColor(eRed, eBlack);
			lMessage.append(SearchNameCharacter(mpCurrentConversationNode->mChildren[luiIndex].miCharacterId));
			lMessage.append(": " + mpCurrentConversationNode->mChildren[luiIndex].macText);
			lGraphic.WriteChars(kiMessage_X + kiIdentation, kiMessage_Y + luiIndex, lMessage.c_str());
		}
   }
}

void cConversationManager::Deinit() {
	mCharacters.resize(0);
	mConversations.resize(0);
}

string cConversationManager::SearchNameCharacter(int luiId) {
	list<cCharacterSpeaker>::iterator lIt;
	for (lIt = mCharacters.begin(); lIt != mCharacters.end(); lIt++) {
		if (lIt->miCharacterId == luiId)
			return lIt->macCharacterName;
	}
	return "";
}

void cConversationManager::ReadCharacters(TiXmlNode* lpRoot) {
	TiXmlElement* lpElem;
	// Read all the characters
	lpElem = lpRoot->FirstChild("Characters")->FirstChild()->ToElement();
	for( lpElem; lpElem; lpElem = lpElem->NextSiblingElement()) {
		cCharacterSpeaker lCharacter;
		// Character ID
		lpElem->QueryIntAttribute("speakerId", &lCharacter.miCharacterId );
		assert(lCharacter.miCharacterId >= 0);
		// Character Name
		const char * lacName = lpElem->GetText();
		assert(lacName);
		lCharacter.macCharacterName = lacName;
		// Add the character to the vector
		mCharacters.push_back( lCharacter );
	}
}


void cConversationManager::ReadConversations(TiXmlNode *lpRoot) {
	// Read all the conversations
	TiXmlElement* lpElem;
	lpElem = lpRoot->FirstChild( "Conversation" )->ToElement();
	for( lpElem; lpElem; lpElem = lpElem->NextSiblingElement("Conversation")) {
		ParseConversation( lpElem );
	}
}

void cConversationManager::ParseConversation( TiXmlElement* pElem ) {
	cConversation lConversation;
	// Read the conversation ID
	const char * lacNameId = pElem->Attribute("nameId");
	assert(lacNameId);
	lConversation.macName = lacNameId;
	// Read the tree
	ParseNode( pElem->FirstChildElement(), &lConversation.mRoot );
	// Add the conversations to the list
	mConversations.push_back(lConversation);
}

void cConversationManager::ParseNode( TiXmlElement *lpElem, cConversationNode *lpCurrentNode ) {
	// Check the stop condition
	if ( lpElem == NULL ) {
		lpCurrentNode->meType = eEndConversation;
		return;
	}
	// Get the type of the XML element
	string lacTag = lpElem->ValueStr();
	if ( lacTag == "Talk" ) {
		// Set the type
		lpCurrentNode->meType = eNormalTalk;
		// Read the text
		const char * lacText = lpElem->GetText();
		assert(lacText);
		lpCurrentNode->macText = lacText;
		// Read the speaker Id
		lpElem->QueryIntAttribute("speakerId", &(lpCurrentNode->miCharacterId));
		assert(lpCurrentNode->miCharacterId >= 0);
		assert(lpCurrentNode->miCharacterId < (int)mCharacters.size());
		// Read the time
		lpElem->QueryFloatAttribute("time", &(lpCurrentNode->mfDuration));
		// Prepare the next node
		cConversationNode lNode;
		lpCurrentNode->mChildren.push_back( lNode );
		// Continue the recursivity
		ParseNode( lpElem->NextSiblingElement(), &(lpCurrentNode->mChildren[0]) );
	}
	else if ( lacTag == "ChooseTalk" ) {
		// Set the type
		lpCurrentNode->meType = eChooseTalk;
		// Read all the options
		TiXmlElement *pElem2 = lpElem->FirstChildElement();
		for (pElem2; pElem2; pElem2 = pElem2->NextSiblingElement()) {
			assert(pElem2);
			assert( pElem2->ValueStr() == "Option" );
			// Add a node to the vector
			cConversationNode lNode;
			lpCurrentNode->mChildren.push_back( lNode );
			// Continue the recursivity
			unsigned luiLastIndex = lpCurrentNode->mChildren.size() - 1;
			ParseNode( pElem2->FirstChildElement(), &(lpCurrentNode->mChildren[ luiLastIndex ]) );
		}
	}
	else {
		assert(0 && "Wrong tag\n");
	}
}

void cConversationManager::StartConversation( const string &lacConversationId ) {
	mbIsInConversation = true;
	mpCurrentConversationNode = new cConversationNode();
	list<cConversation>::iterator it;
	for (it = mConversations.begin(); it != mConversations.end(); it++) {
		if (it->macName == lacConversationId) {
			mpCurrentConversationNode = &(it->mRoot);
			mfMessageTime = mpCurrentConversationNode->mfDuration;
			break;
		}
	}
	this->muiChooseOption = 0;
}

void cConversationManager::NextMessage( unsigned luiNextMessageIndex ) {
	// Checks to make sure that all is right
	assert(mpCurrentConversationNode);
	assert( luiNextMessageIndex < mpCurrentConversationNode->mChildren.size());
	// Select the next node
	bool lbIsChooseNode = (mpCurrentConversationNode->meType == eChooseTalk);
	mpCurrentConversationNode = &(mpCurrentConversationNode->mChildren[ luiNextMessageIndex ]);
	// If the conversation have finished
	if ( mpCurrentConversationNode->meType == eEndConversation ) {
		mpCurrentConversationNode = NULL;
	}
	else if ( lbIsChooseNode ) {
		// This node is the option text
		// We need to choose the next child
		NextMessage(0);
	}
	else {
		// Set the right values
		muiChooseOption = 0;
		mfMessageTime = mpCurrentConversationNode->mfDuration;
	}
}